package me.stone.stanimeclient.core.ui.binding.item

import android.view.View
import android.widget.CompoundButton
import android.widget.CompoundButton.OnCheckedChangeListener
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import kotlinx.coroutines.CoroutineScope


open class ObserverFlowSetting(
    coroutineScope: CoroutineScope,
    @DrawableRes iconResId: Int,
    @StringRes titleResId: Int,
    @StringRes descResId: Int? = null,
    switchChecked: Boolean = false,
    private val onSettingItemClick: (() -> Unit)? = null,
    private val onCheckedChanged: ((Boolean) -> Unit)? = null,
) : ObserverFlowData(coroutineScope), View.OnClickListener, OnCheckedChangeListener {

    val iconResId = observerField(iconResId)
    val titleResId = observerField(titleResId)
    val descriptionResId = observerField(descResId)
    val checked = observerField(switchChecked)

    val showIcon = observerField(true)
    val showDescription = observerField(descResId != null)
    val showSwitch = observerField(onCheckedChanged != null)
    val showDivider = observerField(onSettingItemClick != null && onCheckedChanged != null)

    final override fun onClick(v: View) {
        onSettingItemClick?.invoke() ?: let {
            // 没有设置点击事件，如果 Switch 可用，可以认为点击了 Switch
            if (showSwitch.value) {
                checked.toggle()
            }
        }
    }

    private var toEqualChecked = false

    final override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
        // 保持点击状态一致
        if (toEqualChecked && checked.value == isChecked) {
            toEqualChecked = false
            return
        }
        // 当状态和UI状态在该回调中一致时，表示用户通过状态改变导致UI状态改变
        // 如果当前状态和UI状态不一致时，表示用户点击Switch导致的状态改变
        if (checked.value != isChecked) {
            toEqualChecked = true
            checked.toggle()
            // 因为用户点击Switch导致可以通知状态更新
            onCheckedChanged?.invoke(isChecked)
        }
    }

    private fun ObserverFlowField<Boolean>.toggle() {
        this.update(!value)
    }

    companion object {

        @JvmStatic
        fun newSingleTitleItem(
            coroutineScope: CoroutineScope,
            @DrawableRes iconResId: Int,
            @StringRes titleResId: Int,
            onSettingItemClick: (() -> Unit)
        ) = ObserverFlowSetting(
            coroutineScope = coroutineScope,
            iconResId = iconResId,
            titleResId = titleResId,
            onSettingItemClick = onSettingItemClick
        )

        @JvmStatic
        fun newTitleDescItem(
            coroutineScope: CoroutineScope,
            @DrawableRes iconResId: Int,
            @StringRes titleResId: Int,
            @StringRes descResId: Int,
            onSettingItemClick: (() -> Unit)
        ) = ObserverFlowSetting(
            coroutineScope = coroutineScope,
            iconResId = iconResId,
            titleResId = titleResId,
            descResId = descResId,
            onSettingItemClick = onSettingItemClick
        )

        @JvmStatic
        fun newTitleSwitchItem(
            coroutineScope: CoroutineScope,
            @DrawableRes iconResId: Int,
            @StringRes titleResId: Int,
            checked: Boolean,
            onCheckedChanged: (Boolean) -> Unit
        ) = ObserverFlowSetting(
            coroutineScope = coroutineScope,
            iconResId = iconResId,
            titleResId = titleResId,
            switchChecked = checked,
            onCheckedChanged = onCheckedChanged
        )

        @JvmStatic
        fun newTitleDescSwitchItem(
            coroutineScope: CoroutineScope,
            @DrawableRes iconResId: Int,
            @StringRes titleResId: Int,
            @StringRes descResId: Int,
            checked: Boolean,
            onCheckedChanged: (Boolean) -> Unit
        ) = ObserverFlowSetting(
            coroutineScope = coroutineScope,
            iconResId = iconResId,
            titleResId = titleResId,
            descResId = descResId,
            switchChecked = checked,
            onCheckedChanged = onCheckedChanged
        )

        @JvmStatic
        fun newSettingWithSwitch(
            coroutineScope: CoroutineScope,
            @DrawableRes iconResId: Int,
            @StringRes titleResId: Int,
            @StringRes descResId: Int,
            checked: Boolean,
            onSettingItemClick: () -> Unit,
            onCheckedChanged: (Boolean) -> Unit
        ) = ObserverFlowSetting(
            coroutineScope = coroutineScope,
            iconResId = iconResId,
            titleResId = titleResId,
            descResId = descResId,
            switchChecked = checked,
            onSettingItemClick = onSettingItemClick,
            onCheckedChanged = onCheckedChanged
        )

    }

}